package cn.ddiancan.auth.sms.service;

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

import cn.ddiancan.xddcloud.common.entity.CommonResult;
import cn.ddiancan.xddcloud.ddccore.cache.XddCloudCacheClient;
import cn.ddiancan.xddcloud.psc.oss.service.XddcloudSmsService;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

@Service
@RequiredArgsConstructor
public class XddcloudServerMobileService {

    public static final String BASE_NUMBER = "0123456789";

    private static final String SMS_FREQUENCY_CACHE_KEY = "sms_frequency_cache_key:";

    private static final String SMS_EXPIRE_CACHE_KEY = "sms_expire_cache_key:";

    private final XddcloudSmsService xddcloudSmsService;

    private final XddCloudCacheClient xddCloudCacheClient;

    @Value("${xddcloud.sms.code.size:4}")
    private int smsCodeSize = 4;

    public CommonResult<?> sendSms(String phoneNumber) {
        String frequencyCacheKey = SMS_FREQUENCY_CACHE_KEY.concat(phoneNumber);
        String expireCacheKey = SMS_EXPIRE_CACHE_KEY.concat(phoneNumber);
        if (Boolean.TRUE.equals(xddCloudCacheClient.hasKey(frequencyCacheKey))) {
            return CommonResult.failed(String.format("验证码发送频繁，请%s秒后重试",
                xddCloudCacheClient.getExpire(frequencyCacheKey, TimeUnit.SECONDS)));
        }
        JSONObject jsonObject = new JSONObject();
        String verifyCode = randomNumbers(smsCodeSize);
        jsonObject.put("code", verifyCode);
        xddCloudCacheClient.put(frequencyCacheKey, verifyCode, 1L, TimeUnit.MINUTES);
        xddCloudCacheClient.put(expireCacheKey, verifyCode, 5L, TimeUnit.MINUTES);
        return xddcloudSmsService.sendSms(phoneNumber, jsonObject);
    }

    /**
     * 获得一个只包含数字的字符串
     *
     * @param length 字符串的长度
     * @return 随机字符串
     */
    public static String randomNumbers(int length) {
        return randomString(BASE_NUMBER, length);
    }

    /**
     * 获得一个随机的字符串
     *
     * @param baseString 随机字符选取的样本
     * @param length     字符串的长度
     * @return 随机字符串
     */
    public static String randomString(String baseString, int length) {
        if (!StringUtils.hasText(baseString)) {
            return Strings.EMPTY;
        }
        final StringBuilder sb = new StringBuilder(length);

        if (length < 1) {
            length = 1;
        }
        int baseLength = baseString.length();
        for (int i = 0; i < length; i++) {
            int number = randomInt(baseLength);
            sb.append(baseString.charAt(number));
        }
        return sb.toString();
    }

    /**
     * 获得指定范围内的随机数 [0,limit)
     *
     * @param limit 限制随机数的范围，不包括这个数
     * @return 随机数
     */
    public static int randomInt(int limit) {
        return getRandom().nextInt(limit);
    }

    /**
     * 获取随机数生成器对象
     * ThreadLocalRandom是JDK 7之后提供并发产生随机数，能够解决多个线程发生的竞争争夺。
     * 注意：此方法返回的{@link ThreadLocalRandom}不可以在多线程环境下共享对象，否则有重复随机数问题。
     * 见：https://www.jianshu.com/p/89dfe990295c
     *
     * @return {@link ThreadLocalRandom}
     * @since 3.1.2
     */
    public static ThreadLocalRandom getRandom() {
        return ThreadLocalRandom.current();
    }
}
